from Crypto.Util.number import ( bytes_to_long, getPrime, long_to_bytes, getRandomNBitInteger, ) import random import hashlib from math import gcd import socketserver
KEYSIZE = 512 WELCOME = "welcome to my funny challenge !!! Can you guess right 32 times in a row? " String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"
defexgcd(a, b): if b == 0: return1, 0, a else: x, y, q = exgcd(b, a % b) x, y = y, (x - (a // b) * y) return x, y, q
definvert(a,p): x, y, q = exgcd(a,p) if q != 1: raise Exception("No solution.") else: return (x + p) % p
deflcm(a,b): return a*b // gcd(a,b)
defproof_of_work(): STR = "".join([String[random.randint(0, len(String) - 1)] for _ in range(16)]) HASH = hashlib.sha256(STR.encode()).hexdigest() return STR[:4], STR[4:], HASH
defkeygen(): # part 1 p, q = getPrime(KEYSIZE), getPrime(KEYSIZE) n = p * q g = n + 1 LAMBDA = lcm(p - 1, q - 1)
# part 2 _key = open("key", "r").read() key = [] for i in _key.split("\n"): for j in i[1:-1].split(" "): if int(j) notin key: key.append(int(j)) assert len(key) == 80 #assert key[0] == 119 and key[1] == 241 and key[2] == 718 and key[3] == 647 return n, g, LAMBDA, key
defenc(n, g, m): while1: r = random.randint(2, n - 1) if gcd(r, n) == 1: break c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2) return c
defdec(n, g, LAMBDA, c): L1 = (pow(c, LAMBDA, n ** 2) - 1) // n L2 = (pow(g, LAMBDA, n ** 2) - 1) // n m = (invert(L2, n) * L1) % n return m
classserver(socketserver.BaseRequestHandler): def_recv(self): data = self.request.recv(1024) return data.strip()
defhandle(self): # print("Service start.") # START, END, HASH = proof_of_work() # self._send("SHA-256(?+{}) == {}".format(END, HASH)) # RCV = self._recv().decode() # if RCV != START: # return # flag = open("flag", "rb").read() # self._send(WELCOME) # step 1. keygen for _ in range(32): self._send("round " + str(_+1)) n, g, LAM, KEY = keygen() self._send("Step 1 - KeyGen. This is my public key.") self._send("n = " + str(n)) self._send("g = " + str(g)) # step 2. Phase 1 self._send( "Step 2 - Phase 1. Now, you can give me one ciphertexts,I will return the corresponding plaintext." )
self._send("Please give me one decimal ciphertext.") cipher = int(self._recv().decode()) print(cipher) plaintext = str(dec(n, g, LAM, cipher)) self._send("This is the corresponding plaintext.") self._send(plaintext)
# step 3. challenge self._send( "Step 3 - Challenge. Now, you must give me two decimal plaintexts(m0,m1), I will encry them and return a ciphertext randomly" ) self._send("Give me m0.") plaintext1 = int(self._recv().decode()) self._send("Give me m1.") plaintext2 = int(self._recv().decode())
if ( plaintext1 <= 2 or plaintext2 <= 2 or len(bin(plaintext1)) != len(bin(plaintext2)) ): return R = 2 * random.randint(0, 39) I = random.randint(0, 1) cipher1 = enc(n, g, plaintext1 * plaintext2 * KEY[R]) cipher2 = enc(n, g, plaintext1 * plaintext2 * KEY[R + 1]) self._send("This is a ciphertext.") self._send(str([cipher1, cipher2][I]))
# step 4. Phase 2
self._send( "Step 4 - Phase 2. Now, you can give me some ciphertexts,I will return the corresponding plaintext.But you can not give me the ciphertext that I give you in step 3." ) self._send("Please give me one decimal ciphertext ") cipher = int(self._recv().decode()) plaintext = str(dec(n, g, LAM, cipher)) if int(plaintext) == plaintext1 * plaintext2 * KEY[R] or int(plaintext) == plaintext1 * plaintext2 * KEY[R+1]: print(plaintext) return self._send("This is the corresponding plaintext.") self._send(plaintext)
# step.5 Guess self._send( "Step 5 - Guess. You must tell me which ciphertext was I give you in step 3, 0 or 1(m0 -> c0 , m1 -> c1)?" ) Guess = int(self._recv().decode())
if Guess == I: self._send("Good! You are right") else: self._send("Sorry!") return self._send(flag)
from Crypto.Util.number import ( bytes_to_long, getPrime, long_to_bytes, getRandomNBitInteger, ) import random import hashlib
KEYSIZE = 512 WELCOME = "welcome to my funny challenge !!! Can you guess right 32 times in a row? " String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz" from math import gcd def exgcd(a, b): ifb == 0: return1, 0, a else: x, y, q = exgcd(b, a % b) x, y = y, (x - (a // b) * y) returnx, y, q
def invert(a,p): x, y, q = exgcd(a,p) if q != 1: raise Exception("No solution.") else: return (x + p) % p
def lcm(a,b): returna*b // gcd(a,b)
def proof_of_work(): STR = "".join([String[random.randint(0, len(String) - 1)] for _ in range(16)]) HASH = hashlib.sha256(STR.encode()).hexdigest() return STR[:4], STR[4:], HASH
def enc(n, g, m): while1: r = random.randint(2, n - 1) if gcd(r, n) == 1: break c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2) returnc
def dec(n, g, LAMBDA, c): L1 = (pow(c, LAMBDA, n ** 2) - 1) // n L2 = (pow(g, LAMBDA, n ** 2) - 1) // n m = (invert(L2, n) * L1) % n returnm
from pwn import * from pwnlib.util.iters import mbruteforce from hashlib import sha256
for _ in range(80): sh=remote("47.104.85.225","57811") proof_of_work(sh)
while True: tmp = sh.recvuntil("n = ") n = int(sh.recvuntil("\n")[:-1]) sh.recvuntil("g = ") g = int(sh.recvuntil("\n")[:-1]) sh.recvuntil("decimal ciphertext.\n") sh.sendline("123") sh.recvuntil("Give me m0.\n") sh.sendline("5") sh.recvuntil("Give me m1.\n") sh.sendline("5") sh.recvuntil("This is a ciphertext.\n") c = int(sh.recvuntil("\n")[:-1]) sh.recvuntil("Please give me one decimal ciphertext \n") sh.sendline(str((enc(n,g,5)*c)%(n**2))) sh.recvuntil("This is the corresponding plaintext.\n") m = (int((sh.recvuntil("\n")[:-1]))-5)//25 sh.recvuntil("0 or 1(m0 -> c0 , m1 -> c1)?\n") ifm in s: sh.sendline('1') tmp = sh.recvuntil("\n") elif m in ss: sh.sendline('0') tmp = sh.recvuntil("\n") else: sh.sendline('1') tmp = sh.recvuntil("\n") ifb"Good! You are right" in tmp: s.append(m) elif b"Sorry" in tmp: ss.append(m) sh.close() break print(s) print(ss)
# myRSA from Crypto.Util.number import getPrime,bytes_to_long as b2l from math import gcd import hashlib import random import socketserver
KEYSIZE = 512 alpha = 2.0314159265358979 WELCOME = 'Welcome to use my better RSA!!!!!!So, what do you want now?' menu = '1. encry \n2. getflag\n3. exit' String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz'
defkey_gen(): whileTrue: p,q = getPrime(KEYSIZE),getPrime(KEYSIZE) e = 0x10001 if gcd(e,(p-1)*(q-1)): break key = [getPrime(int(KEYSIZE*alpha)) for_in range(2)] return (p,q,e),key
# encrypto defencry(message,key,p,q,e): k1,k2 = key[0],key[1] x = p**2 * (p + 3*q - 1 ) + q**2 * (q + 3*p - 1) y = 2*p*q + p + q z = k1 + k2 c = pow(b2l(message),e,p*q) return x * c + y * c + z
# get flag defgetflag(flag,key,p,q,e): return encry(flag,key,p,q,e)
classserver(socketserver.BaseRequestHandler): def_recv(self): data = self.request.recv(1024) return data.strip()
defhandle(self): START,END,HASH = proof_of_work() self._send('SHA-256(?+{}) == {}'.format(END,HASH)) RCV = self._recv().decode() if RCV != START: return self._send("I'm a CryptoRookie,so my Crypto system take time, please wait a minute XD!") (p,q,e),key = key_gen() flag = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" self._send(WELCOME) self._send('This is my public key:\nn = {}\ne = {}'.format(str(p*q),str(e))) for_in range(16): self._send(menu) COI = int(self._recv().decode()) if COI == 1: self._send('Give me your message') message = self._recv() self._send('Your encry message:') self._send(str(encry(message,key,p,q,e))) elif COI == 2: self._send('This is your favourite:\n') self._send(str(encry(flag,key,p,q,e))) elif COI == 3: self._send('Bye~') break classForkedServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass
if __name__ == "__main__": HOST, PORT = '0.0.0.0', 10001 server = ForkedServer((HOST, PORT), server) server.allow_reuse_address = True server.serve_forever()
这道题,emmm,也是奇怪的加密方式,
1 2 3 4 5 6 7
def encry(message,key,p,q,e): k1,k2 = key[0],key[1] x = p**2 * (p + 3*q - 1 ) + q**2 * (q + 3*p - 1) y = 2*p*q + p + q z = k1 + k2 c = pow(b2l(message),e,p*q) return x * c + y * c + z
N = n pbar = pw ZmodN = Zmod(N) P.<x> = PolynomialRing(ZmodN) ff = int(pbar) + x x0 = ff.small_roots(X=2^40, beta=0.4)[0] p = int(int(pbar) + x0) n = int(n) q = n // p
tmp = f(p+q) c //= tmp print(long_to_bytes(pow(c,inverse(e,(p-1)*(q-1)),n)))
#! /usr/bin/env python from libnum import n2s, s2n from random import getrandbits from hashlib import sha256 import SocketServer from secret import flag
p, g = 0xb5655f7c97e8007baaf31716c305cf5950a935d239891c81e671c39b7b5b2544b0198a39fd13fa83830f93afb558321680713d4f6e6d7201d27256567b8f70c3, \ 0x85fd9ae42b57e515b7849b232fcd9575c18131235104d451eeceb991436b646d374086ca751846fdfec1ff7d4e1b9d6812355093a8227742a30361401ccc5577
defh2(m): return int(sha256(m).hexdigest(), 16)
defkey_gen(nbits): s = getrandbits(nbits) % p while s.bit_length() < nbits - 2: s = getrandbits(nbits) % p pk = pow(g, s, p) return pk, s
defenc(m, pk): m = s2n(m) e, v = getrandbits(256), getrandbits(256) E, V = pow(g, e, p), pow(g, v, p) s = v + e * h2(n2s(E) + n2s(V)) c = m * pow(pk, e + v, p) % p cap = (E, V, s) return c, cap
defrk_gen(sk, pki, group=9): x, r = getrandbits(512) % p, getrandbits(512) % p prefix = n2s(pow(g, x * sk, p)).rjust(64, '\x00') encoder = [1, -pow(pki, x * sk, p) % p] for i in range(1, group + 1): pkj = getrandbits(512) new_encoder = [1] cur = pow(pkj, x * sk, p) for j in range(1, i + 1): new_encoder.append((encoder[j] + (-1) * cur * encoder[j - 1]) % p) new_encoder.append(encoder[i] * cur * (-1) % p) encoder = new_encoder encoder[-1] += r dd = h2(prefix + n2s(r).rjust(64, '\x00')) | 1 rk = sk * dd return rk, encoder[1:], prefix
classEncHandler(SocketServer.BaseRequestHandler): defhandle(self): self.request.sendall("Welcome to our netdisk system! Our system store only users' ciphertext\n") self.request.sendall("Now you can choose what you wanna do\n") self.request.sendall("1. generate your key\n2. start challenge\n2. get the ciphertext") pk_of_one_user, sk_of_one_user = key_gen(512) cipher = enc(flag, pk_of_one_user) pk, sk = key_gen(512) while1: mul = 1 self.request.sendall('Input your choice\n') self.request.sendall("choice>") choice = self.request.recv(16).strip() if choice == '1': self.request.sendall('Please take good care of it!\n' + hex(pk) + ',' + hex(sk) + '\n') elif choice == '2': group_list = [32, 64, 128, 256] for group in group_list: m = getrandbits(200) plaintext = n2s(m) cur_cipher = enc(plaintext, pk_of_one_user) rk, encoder, prefix = rk_gen(sk_of_one_user, pk, group=group) mul *= rk mul %= p new_cipher = re_enc(rk, cur_cipher) self.request.sendall('The cipher shared to you\n' + str(new_cipher) + '\n') self.request.sendall('prefix, encoder = ' + str((encoder, prefix.encode('hex'))) + '\n') ans = self.request.recv(1024).strip() if int(ans, 16) != m: exit(1) self.request.sendall('You are a clever boy! Now I can share you some other information!\n' + hex(mul) + '\n') elif choice == '3': self.request.sendall(str(cipher) + '\n') exit(1) else: continue
if __name__ == "__main__": HOST, PORT = "0.0.0.0", 1213 server = ThreadedTCPServer((HOST, PORT), EncHandler) server.serve_forever()
defkey_gen(nbits): s = getrandbits(nbits) % p while s.bit_length() < nbits - 2: s = getrandbits(nbits) % p pk = pow(g, s, p) return pk, s
pk_of_one_user, sk_of_one_user = key_gen(512)
基于离散对数问题的公私钥对 $pk \equiv g^{sk} \pmod p$
然乎看到enc的加密方式
1 2 3 4 5 6 7 8
def enc(m, pk): m = s2n(m) e, v = getrandbits(256), getrandbits(256) E, V = pow(g, e, p), pow(g, v, p) s = v + e * h2(n2s(E) + n2s(V)) c = m * pow(pk, e + v, p) % p cap = (E, V, s) return c, cap
可以化为式子: $c \equiv m \cdot pk^{e+v} \equiv m \cdot g^{(e+v)\cdot sk} \equiv m \cdot (E \cdot V) ^ {sk}\pmod p $
那么想获取flag,就要搞到这个私钥sk咯,看看怎么能搞到。
第一目标:拿到sk
可以看到交互提供三个功能,第一个,获取你自己的公私钥对 pk,sk
再看下第三个,返回flag的密文,
然后第二个比较长,核心功能也就在这里了,
1 2 3 4 5 6 7 8 9 10 11 12 13 14
group_list = [32, 64, 128, 256] for group in group_list: m = getrandbits(200) plaintext = n2s(m) cur_cipher = enc(plaintext, pk_of_one_user) rk, encoder, prefix = rk_gen(sk_of_one_user, pk, group=group) mul *= rk mul %= p new_cipher = re_enc(rk, cur_cipher) self.request.sendall('The cipher shared to you\n' + str(new_cipher) + '\n') self.request.sendall('prefix, encoder = ' + str((encoder, prefix.encode('hex'))) + '\n') ans = self.request.recv(1024).strip() if int(ans, 16) != m: exit(1)
流程描述:
他会生成一个随机数m,
然后它的公钥加密m得到cur_cipher,
然后将它的私钥和我们的公钥放进rk_gen这个函数,会得到 rk, encoder, prefix
然后mul = mul * rk % p,
然后用rk,re_enc这个cur_cipher
然后把re_enc后的密文,encoder, prefix 发送给我们。
然后然我们解密m,对了继续,错了拜拜。
循环四次,都通过返回给你mul。
整理逻辑。如果我们都通过了,就能拿到 mul = rk_1 * sk * rk_2 * sk * rk_3 sk * rk_4 % p
for i in range(1, group + 1): pkj = getrandbits(512) new_encoder = [1] cur = pow(pkj, x * sk, p) for j in range(1, i + 1): new_encoder.append((encoder[j] + (-1) * cur * encoder[j - 1]) % p) new_encoder.append(encoder[i] * cur * (-1) % p) encoder = new_encoder
cur = pow(pkj, x * sk, p),pkj是一个随机数,所以cur显然无法直接得到,然后是循环里的 new_encoder.append((encoder[j] + (-1) * cur * encoder[j - 1]) % p)
走出后还来一下 new_encoder.append(encoder[i] * cur * (-1) % p)
这里建议画个美丽的图会稍微清晰一些
可以看到,如果对于cur2那一行,在我们知道 x 的前提下,我们是能够通过第二项获取到 (cur1 + cur2) 的值的,
from random import getrandbits from hashlib import sha256 from Crypto.Util.number import *
def n2s(n): return long_to_bytes(n)
def s2n(n): return bytes_to_long(n)
def h2(m): returnint(sha256(m).hexdigest(), 16)
def key_gen(nbits): s = getrandbits(nbits) % p while s.bit_length() < nbits - 2: s = getrandbits(nbits) % p pk = pow(g, s, p) return pk, s
def enc(m, pk): m = s2n(m) e, v = getrandbits(256), getrandbits(256) E, V = pow(g, e, p), pow(g, v, p) s = v + e * h2(n2s(E) + n2s(V)) c = m * pow(pk, e + v, p) % p cap = (E, V, s) returnc, cap
p, g = ...
#context.log_level = 'debug' sh = remote("47.104.85.225","62351") #sh = remote("0.0.0.0","1213") sh.recvuntil("choice>") sh.sendline("1") sh.recvuntil("Please take good care of it!\n") tmp = sh.recvuntil("\n")[:-1] #获取自己的pk和sk pk,sk = eval(tmp) B=[] sh.recvuntil("choice>") sh.sendline("2") for _ in range(4): sh.recvuntil("The cipher shared to you\n") tmp = sh.recvuntil("\n")[:-1] #获取到 re_enc(m) 后给的 c, (E_, V_, s_) c, (E_, V_, s_) = eval(tmp) sh.recvuntil("prefix, encoder = ") tmp = sh.recvuntil("\n")[:-1] #利用 encoder,prefix 获取r,从而得到dd encoder,prefix = eval(tmp) prefixx = prefix.decode('hex') prefix = int(prefix,16) x = -pow(prefix,sk,p)%p tmp=1 for i in encoder[:-1]: tmp = (i-tmp*x)%p r = (encoder[-1] - tmp*x)%p prefix = n2s(pow(g, x * sk, p)).rjust(64, '\x00') dd = h2(prefixx + n2s(r).rjust(64, '\x00')) | 1 B.append(dd) dd_ = inverse(dd,p-1) #有了dd利用 E_ * V_ 解密m m = inverse(pow(E_*V_,dd_,p),p)*c % p sh.sendline(hex(m)[2:])
sh.recvuntil("You are a clever boy! Now I can share you some other information!\n") tmp = sh.recvuntil("\n")[:-1]